/*
 * Copyright (c) 2013, SRI International
 * All rights reserved.
 * Licensed under the The BSD 3-Clause License;
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 * 
 * http://opensource.org/licenses/BSD-3-Clause
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 
 * Neither the name of the aic-web-praise nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.sri.ai.lpitools.latex.server;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.antlr.runtime.RecognitionException;
import org.apache.log4j.Logger;
import org.apache.xmlrpc.XmlRpcException;

public class LatexFormater {

	private Logger logger = Logger.getLogger(LatexFormater.class);
	
	/**
	 * Public constructor,
	 * 
	 */
	public LatexFormater(){
		//get the script file that is needed and copy it to file system from within the jar
		BufferedReader inFile;
		InputStream stream;
		stream = LatexFormater.class.getResourceAsStream("/textogif");
		inFile = new BufferedReader(new InputStreamReader(stream));
		
		String line;
		try {
			FileWriter fstream = new FileWriter("textogif", false);
			BufferedWriter out = new BufferedWriter(fstream);
			while( (line = inFile.readLine()) != null){
				out.write(line +"\n");
			}
			out.close();
			Runtime.getRuntime().exec("chmod u+x "+"textogif");

		} catch (IOException e) {
			logger.error("Error initializign latex formatter", e);
		}
	}
	
	/**
	 * This function takes the query Result string and formats it to be displayed by the JLatexMath library
	 * @param queryResult
	 * @return
	 * @throws XmlRpcException
	 */
	public String getJLatexMathTranslation(String queryResult) throws XmlRpcException{
		LatexTranslator lt = new LatexTranslator();
		
		try {
			//return the JLatexMath formated query result string
			return lt.translateJLatexMath(queryResult);
		} catch (IllegalArgumentException e) {
			logger.error("Error with JLatexMath translation", e);
			throw new XmlRpcException("Error with JLatexMath translation, IllegalArgumentException caught", e);
		} catch (RecognitionException e) {
			logger.error("Error with JLatexMath translation", e);
			throw new XmlRpcException("Error with JLatexMath translation, RecognitionException caught", e);
		}
	}
	
	/**
	 * This function takes the query Result string and formats it to be displayed by the TexLive process and then builds the TexLive image
	 * It returns the image as a base64 encoded string
	 * @param queryResult
	 * @return
	 * @throws XmlRpcException
	 */
	public String getTexLiveImage(String queryResult) throws XmlRpcException{

		File temp = null;
		try {
			//get the latextranslator object
			LatexTranslator lt = new LatexTranslator();

			//translate the query Result string into a latex string for the tex live process
			String tex = lt.translateTexLive(queryResult);
			//build the full tex string
			String fullTex = "\\documentclass{article}" +
					"\\usepackage{algorithm2e}"+
					"\\usepackage{color}" +
					"\\pagestyle{empty}"+
					"\\begin{document}"+
					"\\color{black}" +
					"\\pagecolor{white}" +
					"\\begin{algorithm}" +
					"\\dontprintsemicolon" +
					tex + 
					"\\end{algorithm}"+
					"\\end{document}";
			//get the current directory
			String currentDir = new File(".").getAbsolutePath();
			File currentDirectory = new File(currentDir);
			//create a temp file to hold the latex string

			temp =File.createTempFile("latex", ".tex", currentDirectory);
			temp.setWritable(true);
			BufferedWriter out = new BufferedWriter(new FileWriter(temp));
			out.write(fullTex);
			out.close();

			//check that there is not a iamge file with the same name already, if there is delete it
			File imageOld = new File(temp.getCanonicalPath().replace(".tex", ".png"));
			if(imageOld.exists()){
				imageOld.delete();
			}
			//run process to build the image file from the above latex string
			Process p = Runtime.getRuntime().exec("./textogif -dpi 300 -png " + temp.getCanonicalPath());
			String s = null;
			BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
			BufferedReader stdOut = new BufferedReader(new InputStreamReader(p.getInputStream()));

			//clear the streams, but ignore the data
			while((s = stdOut.readLine()) != null){
				logger.debug(s);
			}
			while((s = stdError.readLine()) != null){
				logger.debug(s);
			}

			//check that the image file was properly built
			File imageNew = new File(temp.getCanonicalPath().replace(".tex", ".png"));
			try {
				if(!imageNew.exists()){
					throw new XmlRpcException("Error with TEXLive image creating");
				}
	
				//get the byte array of the above image file
				byte[] picture = new byte[(int) imageNew.length()];
				FileInputStream fileInputStream = new FileInputStream(imageNew);
				fileInputStream.read(picture);
				//encode byte array into a base 64 string 
				String base64 = Base64.encodeToString(picture, false);
				base64 = "data:image/png;base64," + base64;  
		
				fileInputStream.close();
				//return base64 encoded string
				return base64;
			} finally {
				//cleanup the image file
				imageNew.delete();
			}

		} catch (IOException e) {
			throw new XmlRpcException("Error with TEXLive image creating, IOException caught", e);
		} catch (IllegalArgumentException e) {
			throw new XmlRpcException("Error with TEXLive image creating, IllegalArgumentException caught", e);
		} catch (RecognitionException e) {
			throw new XmlRpcException("Error with TEXLive image creating, RecognitionException caught", e);
		}  finally {
			//make sure that we delete the temporary files
			if (temp != null) {
				try {
					File logFile = new File(temp.getCanonicalPath().replace(".tex", ".log"));
					logFile.delete();
				} catch (IOException e) {
					logger.error("Unable to delete tex log file");
				}
				try {
					File augFile = new File(temp.getCanonicalPath().replace(".tex", ".aux"));
					augFile.delete();
				} catch (IOException e) {
					logger.error("unable to delete tex aux file");
				}
				temp.delete();
			}
		}
	}


	

}
